/*
 * EBFV1_loadVertex.cpp
 *
 *  Created on: 16/09/2012
 *      Author: rogsoares
 */

#include "EBFV1_preprocessor.h"


void loadNodalVolumes(ifstream &fid, TMesh *pTMesh_data){
	GVD_list globalList;		// list of lists. Store list for each domain
	PetscPrintf(PETSC_COMM_WORLD,"Loading Nodes...\t");
	int ID, i;
	double vol,wvol;
	double vt = 0.0;
	string str, sdata[10];
	getline(fid,str,'\n');				//	Mesh dimension:
	getline(fid,str,'\n');
	pTMesh_data->setMeshDim( atoi(str.c_str()) );
	getline(fid,str,'\n');				//	Number of domains:
	getline(fid,str,'\n');
	int ndom = atoi(str.c_str());		//	2
	pTMesh_data->setNumDomains( ndom );
	pTMesh_data->set_data_lists();
	getline(fid,str,'\n');				//	Domains' flag list:
	for (i=0; i<ndom; i++){
		getline(fid,str,'\n');
		pTMesh_data->setdomFlags(i,atoi(str.c_str()));
	}
	pTMesh_data->mapDomainsFlags();
	getline(fid,str,'\n');					// For each node: ID - numRemoteCopies - x - y - z - nodalVolume - weightedvolume
	for (int i=0; i<pTMesh_data->getNumDomains(); i++){
		VertexData* vdata;
		VD_list vertexList;					// List for domain dom vertices
		getline(fid,str,'\n');				// Nodes over domain: XXXX
		while (1){
			fid >> sdata[0];
			if ( !sdata[0].compare("end") ){
				break;
			}
			ID = atoi(sdata[0].c_str());
			if (!ID){
				throw Exception(__LINE__,__FILE__,"ID zero\n");
			}
			fid >> sdata[0] >> sdata[1] >> sdata[2] >> sdata[3] >> sdata[4] >> sdata[5] >> sdata[6];

			// do not divide vol by number of remote copies!
			vol = strtod(sdata[5].c_str(), 0);

			// Weighting volume by porosity in useless.
			wvol = vol;
			if (vol == .0){
				char msg[256]; sprintf(msg,"Node %d has null volume!",ID);
				throw Exception(__LINE__,__FILE__,msg);
			}
			// TODO: volume NOT in parallel
			vt += vol;///((double)nrc+1.0);
			vdata = new VertexData;
			vdata->ID = ID;
			vdata->flag = atoi(sdata[0].c_str());
			vdata->numRC = atoi(sdata[1].c_str());
			vdata->x = strtod(sdata[2].c_str(), 0);;
			vdata->y = strtod(sdata[3].c_str(), 0);;
			vdata->z = strtod(sdata[4].c_str(), 0);;
			vdata->volume = vol;
			vdata->weighted_volume = wvol;
			vertexList.push_back(vdata);
		}
		getline(fid,str,'\n');
		globalList.push_back(vertexList);
	}
	transferVertexDataFromListToMatrix(pTMesh_data,globalList);
	PetscPrintf(PETSC_COMM_WORLD,"done.\n");
}

/*
 * It's intended to work with an matrix and not a list.
 */
void transferVertexDataFromListToMatrix(TMesh *pTMesh_data, GVD_list &globalList){
	std::set<int> setIDs;	// Counting Number of Vertices By their IDs
	int i = 0;
	GVD_list::iterator GVD_iter = globalList.begin();
	for (;GVD_iter != globalList.end(); GVD_iter++){
		VD_list vdlist = *GVD_iter;
		int nrows = (int)vdlist.size();
		pTMesh_data->vertices_list[i].allocateMemory(nrows,1);

		int j = 0;
		VD_list::iterator vdlist_iter = vdlist.begin();
		for (;vdlist_iter != vdlist.end(); vdlist_iter++){
			pTMesh_data->vertices_list[i].setValue(j++,0,*vdlist_iter);
			setIDs.insert( (*vdlist_iter)->ID );
		}
		i++;
	}
	int n = (int)setIDs.size();
	pTMesh_data->setNumGVertices(n);
	setIDs.clear();
	globalList.clear();
}

// for debug purposes only
void printVerticesData(TMesh *pTMesh_data){
	int nrows, ncols;
	int ndom = pTMesh_data->getNumDomains();
	for (int i=0; i<ndom; i++){
		pTMesh_data->vertices_list[i].getSize(nrows,ncols);
		for (int j=0; j<nrows; j++){
			VertexData* vdata = pTMesh_data->vertices_list[i].getValue(j,0);
			cout << setprecision(5) << scientific;
			cout << nrows << "\t";
			cout << vdata->ID << "\t";
			cout << vdata->flag  << "\t";
			cout << vdata->numRC << "\t";
			cout << vdata->x << "\t";
			cout << vdata->y << "\t";
			cout << vdata->z << "\t";
			cout << vdata->volume << "\t";
			cout << vdata->weighted_volume << "\n";
		}
	}
}
